package com.jlt.security;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.security.web.util.AntUrlPathMatcher;
import org.springframework.security.web.util.UrlMatcher;
import org.springframework.stereotype.Component;

import com.jlt.service.account.ResourceManager;

/* 
 *  
 * 最核心的地方，就是提供某个资源对应的权限定义，即getAttributes方法返回的结果。 
 * 注意，我例子中使用的是AntUrlPathMatcher这个path matcher来检查URL是否与资源定义匹配， 
 * 事实上你还要用正则的方式来匹配，或者自己实现一个matcher。 
 *  
 * 此类在初始化时，应该取到所有资源及其对应角色的定义 
 *  
 * 说明：对于方法的spring注入，只能在方法和成员变量里注入， 
 * 如果一个类要进行实例化的时候，不能注入对象和操作对象， 
 * 所以在构造函数里不能进行操作注入的数据。 
 */
@Component
public class JltInvocationSecurityMetadataSourceService implements
		FilterInvocationSecurityMetadataSource {
	/**
	 * Logger for this class
	 */
	private static final Logger logger = Logger
			.getLogger(JltInvocationSecurityMetadataSourceService.class);

	@Autowired
	private ResourceManager resourceManager;

	private UrlMatcher urlMatcher = new AntUrlPathMatcher();
	private static Map<String, Collection<ConfigAttribute>> resourceMap = null;

	public void loadResourceDefine() throws Exception {
		resourceMap = new HashMap<String, Collection<ConfigAttribute>>();

		LinkedHashMap<String, String> rescsMap = resourceManager
				.getRequestMap();

		// 通过数据库中的信息设置，resouce和role
		Iterator<String> ite = rescsMap.keySet().iterator();
		while (ite.hasNext()) {
			String resUrl=ite.next();
			String authorityStr = rescsMap.get(resUrl);
			String[] authoritys = authorityStr.split(",");
			Collection<ConfigAttribute> atts = new ArrayList<ConfigAttribute>();
			for (String auth : authoritys) {
				ConfigAttribute ca = new SecurityConfig("A_"+auth);
				atts.add(ca);
			}
			// 把资源放入到spring security的resouceMap中
			resourceMap.put(resUrl, atts);
		}

		/*
		 * //通过硬编码设置，resouce和role resourceMap = new HashMap<String,
		 * Collection<ConfigAttribute> atts = new ArrayList<ConfigAttribute>();
		 * ConfigAttribute ca = new SecurityConfig("A_MODIFY_USER");
		 * atts.add(ca); resourceMap.put("/account/user!save*", atts);
		 * resourceMap.put("/account/user*", atts);
		 */

	}

	// According to a URL, Find out permission configuration of this URL.
	public Collection<ConfigAttribute> getAttributes(Object object)
			throws IllegalArgumentException {
		if (logger.isDebugEnabled()) {
			logger.debug("getAttributes(Object) - start"); //$NON-NLS-1$  
		}
		// guess object is a URL.
		String url = ((FilterInvocation) object).getRequestUrl();
		Iterator<String> ite = resourceMap.keySet().iterator();
		while (ite.hasNext()) {
			String resURL = ite.next();

			if (urlMatcher.pathMatchesUrl(resURL, url)) {
				Collection<ConfigAttribute> returnCollection = resourceMap
						.get(resURL);
				if (logger.isDebugEnabled()) {
					logger.debug("getAttributes(Object) - end"); //$NON-NLS-1$  
				}
				return returnCollection;
			}
		}
		if (logger.isDebugEnabled()) {
			logger.debug("getAttributes(Object) - end"); //$NON-NLS-1$  
		}
		return null;
	}

	public boolean supports(Class<?> clazz) {
		return true;
	}

	public Collection<ConfigAttribute> getAllConfigAttributes() {
		return null;
	}

	public ResourceManager getResourceManager() {
		return resourceManager;
	}
	
	public void setResourceManager(ResourceManager resourceManager) {
		this.resourceManager = resourceManager;
	}

	public static void setResourceMap(
			Map<String, Collection<ConfigAttribute>> resourceMap) {
		JltInvocationSecurityMetadataSourceService.resourceMap = resourceMap;
	}

}